#include "stdafx.h"

#include "../../../include/3rd_part/xml/TiXmlUtility.h"

using namespace Common;
Vector3 TiXmlUtility::StringToVector3( const String& strValue )
{
	//TODO: check the value format validation
	std::stringstream ss;
	Vector3 ret;	

	ss << strValue;
	ss >> ret.x >> ret.y >> ret.z;
	ss.clear();

	return ret;
}

String TiXmlUtility::Vector3ToString( const Common::Vector3& vValue)
{
	std::stringstream ss;
	ss.precision(3);
	ss.setf( ss.fixed );

	ss << vValue.x << " " << vValue.y << " " << vValue.z;
	return ss.str();
}

String TiXmlUtility::FloatToString( Real Value )
{
	std::stringstream ss;
	ss.precision(3);
	ss.setf( ss.fixed );

	ss << Value;
	return ss.str();
}

Real TiXmlUtility::StringToFloat( String strValue )
{
	return (float)::atof( strValue.c_str() );
}

Vector4 TiXmlUtility::StringToVector4( const String& strValue )
{
	//TODO: check the value format validation
	std::stringstream ss;
	Vector4 ret;	

	ss << strValue;
	ss >> ret.x >> ret.y >> ret.z >> ret.w;
	ss.clear();

	return ret;
}

String TiXmlUtility::Vector4ToString( const Vector4& vValue )
{
	std::stringstream ss;
	ss.precision(3);
	ss.setf( ss.fixed );

	ss << vValue.x << " " << vValue.y << " " << vValue.z << " " << vValue.w;

	return ss.str();
}

/*
<transform>
			<row0>	-0.768986 0.000000 -0.443975	</row0>
			<row1>	0.000000 0.887950 0.000000		</row1>
			<row2>	0.443975 0.000000 -0.768986		</row2>
			<row3>	40.299999 16.800001 64.899994	</row3>
</transform>
*/

Matrix4 TiXmlUtility::ReadMatrix( TiXmlHandle ptrDataSec )
{
	String row0 = ptrDataSec.FirstChild( "row0" ).ToElement()->GetText();
	String row1 = ptrDataSec.FirstChild( "row1" ).ToElement()->GetText();
	String row2 = ptrDataSec.FirstChild( "row2" ).ToElement()->GetText();
	String row3 = ptrDataSec.FirstChild( "row3" ).ToElement()->GetText();

	Vector3 vRow0 = TiXmlUtility::StringToVector3( row0 );
	Vector3 vRow1 = TiXmlUtility::StringToVector3( row1 );
	Vector3 vRow2 = TiXmlUtility::StringToVector3( row2 );
	Vector3 vRow3 = TiXmlUtility::StringToVector3( row3 );

	return Matrix4(vRow0.x,vRow1.x,vRow2.x,vRow3.x, vRow0.y,vRow1.y,vRow2.y,vRow3.y, vRow0.z,vRow1.z,vRow2.z,vRow3.z, 0.0f,0.0f,0.0f,1.0f);
}

void TiXmlUtility::WriteMatrix( const Matrix4& matrix, TiXmlNode* pDataSec )
{
	std::stringstream ss;
	std::string strRow;

	for( int iRow = 0; iRow != 4; ++iRow )
	{
		Vector3 vRowValue;
		for( int iCol = 0; iCol != 3; ++iCol )
			vRowValue[iCol] = matrix[iRow][iCol];
		
		ss << "row" << iRow << std::endl;
		ss >> strRow;
		ss.clear();
		TiXmlElement rRowNode( strRow );

		rRowNode.InsertEndChild( TiXmlText(TiXmlUtility::Vector3ToString( vRowValue )) );

		pDataSec->InsertEndChild( rRowNode );
	}
}


/*
<AABB>
		<Max>vector3</Max>
		<Min>vector3</Min>
</AABB>
*/

AxisAlignedBox TiXmlUtility::ReadAABB( TiXmlHandle ptrDataSec )
{
	AxisAlignedBox AABB;

	String strMax = ptrDataSec.FirstChild("max").ToElement()->GetText();
	String strMin = ptrDataSec.FirstChild("min").ToElement()->GetText();

	Vector3 vMin = TiXmlUtility::StringToVector3( strMin );
	Vector3 vMax = TiXmlUtility::StringToVector3( strMax );

	AABB.setExtents(vMin,vMax);

	return AABB;
}

void TiXmlUtility::WriteAABB( const Common::AxisAlignedBox& rBB, TiXmlNode* pDataSec )
{
	TiXmlElement maxNode("max");
	maxNode.InsertEndChild( TiXmlText( TiXmlUtility::Vector3ToString( rBB.getMaximum() ) ) );
	pDataSec->InsertEndChild( maxNode );

	TiXmlElement minNode("min");
	minNode.InsertEndChild( TiXmlText( TiXmlUtility::Vector3ToString( rBB.getMinimum() ) ) );
	pDataSec->InsertEndChild( minNode );
}

/*
<Plane>
	<normal> vector3	</normal>
	<d>	float </d>
</Plane>
*/
void TiXmlUtility::WritePlane( const Common::Plane& rPlane, TiXmlNode* pDataSec )
{
	TiXmlNode* pNormalElement = new TiXmlElement("normal");
	pNormalElement = pDataSec->InsertEndChild( *pNormalElement );
	TiXmlNode* pNormalValue = new TiXmlText( TiXmlUtility::Vector3ToString(rPlane.normal) );
	pNormalElement->InsertEndChild( *pNormalValue );

	TiXmlNode* pDirectionElement = new TiXmlElement("d");
	pDirectionElement = pDataSec->InsertEndChild( *pDirectionElement );
	TiXmlNode* pDirectionValue = new TiXmlText( TiXmlUtility::FloatToString(rPlane.d) );
	pDirectionElement->InsertEndChild( *pDirectionValue );
}

Common::Plane TiXmlUtility::ReadPlane( TiXmlHandle ptrDataSec )
{
	String strNormal = ptrDataSec.FirstChild("normal").ToElement()->GetText();
	String strDistance = ptrDataSec.FirstChild("d").ToElement()->GetText();

	Vector3 vNormal = TiXmlUtility::StringToVector3( strNormal );
	Real fDistance = TiXmlUtility::StringToFloat( strDistance );

	return Common::Plane(vNormal,fDistance);
}


